{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "initial_id",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    ""
   ]
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 1  定义工具",
   "id": "7e771d4e37894461"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-01T12:02:43.586898Z",
     "start_time": "2025-10-01T12:02:38.618662Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import os\n",
    "\n",
    "import dotenv\n",
    "from docutils.nodes import document\n",
    "from langchain.agents import create_tool_calling_agent, AgentExecutor\n",
    "from langchain_community.tools import TavilySearchResults\n",
    "from langchain_core.chat_history import BaseChatMessageHistory\n",
    "from langchain_core.messages import HumanMessage\n",
    "from langchain_core.runnables import RunnableWithMessageHistory\n",
    "from langchain_openai import OpenAIEmbeddings\n",
    "from ollama import embeddings\n",
    "\n",
    "# 定义 AVILY_KEY 密钥\n",
    "os.environ[\"TAVILY_API_KEY\"] = \"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\"\n",
    "\n",
    "# 查询 Tavily 搜索 API\n",
    "search = TavilySearchResults(max_results = 1)\n",
    "\n",
    "# 执行查询\n",
    "res = search.invoke(\"今天上海天气怎么样\")\n",
    "print(res)"
   ],
   "id": "8ba9ffee49a7139d",
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/var/folders/9p/r71fhhs11052m2r7x4gfc5b80000gn/T/ipykernel_91842/1470901005.py:10: LangChainDeprecationWarning: The class `TavilySearchResults` was deprecated in LangChain 0.3.25 and will be removed in 1.0. An updated version of the class exists in the :class:`~langchain-tavily package and should be used instead. To use it run `pip install -U :class:`~langchain-tavily` and import as `from :class:`~langchain_tavily import TavilySearch``.\n",
      "  search = TavilySearchResults(max_results = 1)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[{'title': '中国气象局-天气预报-城市预报- 上海', 'url': 'https://weather.cma.cn/web/weather/58367.html', 'content': '|  |  |  |  |  |  |  |  |  |\\n ---  ---  ---  --- \\n| 时间 | 08:00 | 11:00 | 14:00 | 17:00 | 20:00 | 23:00 | 02:00 | 05:00 |\\n| 天气 |\\n| 气温 | 29.1℃ | 29.9℃ | 29.5℃ | 26℃ | 24.9℃ | 23.8℃ | 23.8℃ | 23.9℃ |\\n| 降水 | 0.9mm | 1.5mm | 5.4mm | 1.6mm | 1.6mm | 0.1mm | 无降水 | 无降水 |\\n| 风速 | 3.3m/s | 3.3m/s | 3.3m/s | 2.9m/s | 2.7m/s | 3.3m/s | 3.1m/s | 3.1m/s |\\n| 风向 | 西北风 | 西北风 | 西北风 | 东北风 | 东南风 | 西北风 | 西北风 | 西北风 |\\n| 气压 | 1013.2hPa | 1012.7hPa | 1012hPa | 1012.3hPa | 1013.3hPa | 1013.3hPa | 1012.7hPa | 1012.2hPa | [...] |  |  |  |  |  |  |  |  |  |\\n ---  ---  ---  --- \\n| 时间 | 11:00 | 14:00 | 17:00 | 20:00 | 23:00 | 02:00 | 05:00 | 08:00 |\\n| 天气 |\\n| 气温 | 34℃ | 34.3℃ | 32℃ | 28.6℃ | 28.1℃ | 27.3℃ | 26.7℃ | 28.6℃ |\\n| 降水 | 2.3mm | 2.3mm | 2.3mm | 2.3mm | 无降水 | 无降水 | 无降水 | 无降水 |\\n| 风速 | 3.3m/s | 3.3m/s | 3m/s | 2.8m/s | 3.2m/s | 3.1m/s | 3m/s | 3.3m/s |\\n| 风向 | 西南风 | 西南风 | 东南风 | 东北风 | 东南风 | 东南风 | 东南风 | 西南风 |\\n| 气压 | 1017.1hPa | 1014.6hPa | 1014.3hPa | 1015.6hPa | 1015hPa | 1014.3hPa | 1013.7hPa | 1014.6hPa | [...] |  |  |  |  |  |  |  |  |  |\\n ---  ---  ---  --- \\n| 时间 | 08:00 | 11:00 | 14:00 | 17:00 | 20:00 | 23:00 | 02:00 | 05:00 |\\n| 天气 |\\n| 气温 | 27.2℃ | 27℃ | 27.9℃ | 26.9℃ | 24.5℃ | 23.6℃ | 23.6℃ | 23.6℃ |\\n| 降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 |\\n| 风速 | 3.3m/s | 3.1m/s | 3.3m/s | 2.9m/s | 2.7m/s | 3.1m/s | 2.9m/s | 3.1m/s |\\n| 风向 | 东北风 | 东北风 | 东北风 | 东北风 | 东南风 | 东南风 | 东南风 | 东南风 |\\n| 气压 | 1014hPa | 1014hPa | 1012.5hPa | 1012.8hPa | 1014hPa | 1013.1hPa | 1012.3hPa | 1012.2hPa |', 'score': 0.78054583}]\n"
     ]
    }
   ],
   "execution_count": 1
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 2 定义Retriever",
   "id": "bbad2b4d178f8de3"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-01T12:17:51.493599Z",
     "start_time": "2025-10-01T12:17:40.565212Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from langchain_community.vectorstores import FAISS\n",
    "from langchain_text_splitters import RecursiveCharacterTextSplitter\n",
    "from langchain_community.document_loaders import WebBaseLoader\n",
    "import dotenv\n",
    "from langchain_openai import OpenAIEmbeddings\n",
    "\n",
    "dotenv.load_dotenv()\n",
    "# 1. 提供一个大模型\n",
    "os.environ['OPENAI_API_KEY'] = os.getenv(\"OPENAI_API_KEY1\")\n",
    "os.environ['OPENAI_BASE_URL'] = os.getenv(\"OPENAI_BASE_URL\")\n",
    "\n",
    "embedding_model = OpenAIEmbeddings()\n",
    "\n",
    "# 2.加载HTML内容为一个文档对象\n",
    "loader = WebBaseLoader(\"https://zh.wikipedia.org/wiki/%E7%8C%AB\")\n",
    "docs = loader.load()\n",
    "# print(docs)\n",
    "\n",
    "# 3.分割文档\n",
    "splitter = RecursiveCharacterTextSplitter(\n",
    "    chunk_size = 1000,\n",
    "    chunk_overlap = 200\n",
    ")\n",
    "\n",
    "documents = splitter.split_documents(docs)\n",
    "\n",
    "# 4.向量化 得到向量数据库对象\n",
    "vector = FAISS.from_documents(documents, embedding_model)\n",
    "\n",
    "# 5.创建检索器\n",
    "retriever = vector.as_retriever()\n",
    "# 测试检索结果\n",
    "print(retriever.invoke(\"猫的特征\")[0])"
   ],
   "id": "8f9f950b3fc96800",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "page_content='感官[编辑]\n",
      "貓的感官適於狩獵。在哺乳類動物中，貓的聽覺、視覺、嗅覺、味覺、觸覺極敏銳。\n",
      "\n",
      "視覺[编辑]\n",
      "貓的瞳孔能縮得如線般狹小\n",
      "貓的瞳孔變化\n",
      "貓在晝間視覺縱不及人類，夜視能力與追蹤視覺上之活動物件卻相當出色，夜視能力是人類的六倍，雖然綜合色彩計算整體視覺系數則僅及人類的十分之一。貓的眼睛具有微光觀察能力，即使只有微弱月光都可分辨物件，有關光線入貓眼後可放大40至50倍處理，令貓具有夜間活動的能力，即使在黑暗的地下室貓咪依然能活動自如。強光下，貓會將瞳孔縮得如線般狹小，以減少對視網膜的傷害，但視野會因而縮窄。由於貓眼具備高幀與高分辨率視覺，故此電視機極微細之動靜對貓而言亦成逐格跳躍之畫面。[51]\n",
      "另外，不只是光線會影響貓的瞳孔，感情也會。一般而言貓放鬆的時候瞳孔會縮小，而緊張時會放大。\n",
      "貓的視網膜背面有一層藍綠色如熒光一般的薄膜（Tapetum Lucidum），可增加在暗處的視力。閃光中，貓眼能呈現各式各樣顔色。如同多數食肉動物，貓眼長在臉上朝正前方，賦予其遼闊的視野，單一貓眼視野為100度，雙眼視野為285度，加上頸旋靈活，總計視野比人類雙眼僅100度靈活得多。不過，貓僅能聚焦其前30厘米至3米之物件，相對人類而言屬大近視。\n",
      "貓對三原色的辨識力很差，相對人類而言，貓有黃藍色盲且紅綠色辨成灰黃色，與狗相似。關於貓的夜視能力，生物學家發現牛磺酸對貓的視力起了很大作用，貓本身不能合成牛磺酸，必須由外攝取。缺乏牛磺酸，會使視力及夜視能力變差，影響夜間活動。據生物學家稱，貓經常捕鼠，是因老鼠體內含牛磺酸。[52][53]\n",
      "紫外線可以通過貓的晶状体。\n",
      "當四周光線微弱，貓會用感覺毛來改善行動力與感知能力。感覺毛主要分布於鼻子兩側、下巴、雙眼上方、兩頰也有數根。感覺毛可感受非常微弱的空氣波動，視野不清時也能協助辨識阻礙位置。鬍鬚尖端與雙耳連成一線，恰是身體能通過障礙的最小範圍，故貓可在黑夜中快速判斷地形能否通過。\n",
      "貓有第三眼瞼，當貓眼睑張開時，眨眼時第三眼瞼會從旁稍微遮蓋眼睛。若貓生病，或是睡眠，笑著，此眼皮會縮回一部分。若貓長時間嶄露第三眼瞼，表示它的健康有問題。' metadata={'source': 'https://zh.wikipedia.org/wiki/%E7%8C%AB', 'title': '猫 - 维基百科，自由的百科全书', 'language': 'zh'}\n"
     ]
    }
   ],
   "execution_count": 8
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 3 创建工具、工具集",
   "id": "7ff659f86e746d3b"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-01T12:21:08.414996Z",
     "start_time": "2025-10-01T12:21:08.051098Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from langchain_core.tools import create_retriever_tool\n",
    "\n",
    "# 创建一个工具来检索文档\n",
    "retriever_tool = create_retriever_tool(\n",
    "    retriever = retriever,\n",
    "    name=\"wiki_search\",\n",
    "    description = \"搜索维基百科\"\n",
    ")\n",
    "# 构建工具集\n",
    "tools = [search,retriever_tool]"
   ],
   "id": "812ba5ff86cdf89b",
   "outputs": [],
   "execution_count": 9
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 4 语言模型调用工具",
   "id": "2d2c9c079416d23f"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-01T12:24:10.928874Z",
     "start_time": "2025-10-01T12:24:04.710165Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from langchain_openai import ChatOpenAI\n",
    "from  langchain_core.messages import HumanMessage\n",
    "# 获取大模型\n",
    "model = ChatOpenAI(model=\"gpt-4o-mini\")\n",
    "\n",
    "# 模型绑定工具\n",
    "model_with_tools = model.bind_tools(tools)\n",
    "\n",
    "# 根据输入自动调用工具\n",
    "messages = [HumanMessage(content=\"今天上海天气怎么样\")]\n",
    "response = model_with_tools.invoke(messages)\n",
    "print(f\"ContentString: {response.content}\")\n",
    "print(f\"ToolCalls: {response.tool_calls}\")"
   ],
   "id": "82e07b59fc556e93",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ContentString: \n",
      "ToolCalls: [{'name': 'tavily_search_results_json', 'args': {'query': '上海天气预报'}, 'id': 'call_deWtLtCU6yBKDCLNBbGmfgC1', 'type': 'tool_call'}]\n"
     ]
    }
   ],
   "execution_count": 11
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 5 创建Agent程序(使用通用方式)",
   "id": "20ce92737a95e554"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-01T12:25:23.888429Z",
     "start_time": "2025-10-01T12:25:18.330267Z"
    }
   },
   "cell_type": "code",
   "source": [
    "\n",
    "\n",
    "from langchain import hub\n",
    "\n",
    "prompt = hub.pull(\"hwchase17/openai-functions-agent\")\n",
    "\n",
    "print(prompt.messages)"
   ],
   "id": "3708d49b81dd84de",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=[], input_types={}, partial_variables={}, template='You are a helpful assistant'), additional_kwargs={}), MessagesPlaceholder(variable_name='chat_history', optional=True), HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], input_types={}, partial_variables={}, template='{input}'), additional_kwargs={}), MessagesPlaceholder(variable_name='agent_scratchpad')]\n"
     ]
    }
   ],
   "execution_count": 12
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-01T12:27:34.920506Z",
     "start_time": "2025-10-01T12:27:34.909905Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from langchain.agents import create_tool_calling_agent,AgentExecutor\n",
    "\n",
    "# 创建Agent对象\n",
    "agent = create_tool_calling_agent(model, tools, prompt)\n",
    "\n",
    "# 创建AgentExecutor对象\n",
    "agent_executor = AgentExecutor(agent=agent, tools=tools,verbose= True)"
   ],
   "id": "dd57981f7b08517b",
   "outputs": [],
   "execution_count": 17
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 6 运行Agent",
   "id": "5dfcc28d789d2b45"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-01T12:28:42.744583Z",
     "start_time": "2025-10-01T12:28:18.748650Z"
    }
   },
   "cell_type": "code",
   "source": "print(agent_executor.invoke({\"input\": \"猫的特征\"}))",
   "id": "fa17d7456d1ded5b",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new AgentExecutor chain...\u001B[0m\n",
      "\u001B[32;1m\u001B[1;3m\n",
      "Invoking: `wiki_search` with `{'query': '猫的特征'}`\n",
      "\n",
      "\n",
      "\u001B[0m\u001B[33;1m\u001B[1;3m感官[编辑]\n",
      "貓的感官適於狩獵。在哺乳類動物中，貓的聽覺、視覺、嗅覺、味覺、觸覺極敏銳。\n",
      "\n",
      "視覺[编辑]\n",
      "貓的瞳孔能縮得如線般狹小\n",
      "貓的瞳孔變化\n",
      "貓在晝間視覺縱不及人類，夜視能力與追蹤視覺上之活動物件卻相當出色，夜視能力是人類的六倍，雖然綜合色彩計算整體視覺系數則僅及人類的十分之一。貓的眼睛具有微光觀察能力，即使只有微弱月光都可分辨物件，有關光線入貓眼後可放大40至50倍處理，令貓具有夜間活動的能力，即使在黑暗的地下室貓咪依然能活動自如。強光下，貓會將瞳孔縮得如線般狹小，以減少對視網膜的傷害，但視野會因而縮窄。由於貓眼具備高幀與高分辨率視覺，故此電視機極微細之動靜對貓而言亦成逐格跳躍之畫面。[51]\n",
      "另外，不只是光線會影響貓的瞳孔，感情也會。一般而言貓放鬆的時候瞳孔會縮小，而緊張時會放大。\n",
      "貓的視網膜背面有一層藍綠色如熒光一般的薄膜（Tapetum Lucidum），可增加在暗處的視力。閃光中，貓眼能呈現各式各樣顔色。如同多數食肉動物，貓眼長在臉上朝正前方，賦予其遼闊的視野，單一貓眼視野為100度，雙眼視野為285度，加上頸旋靈活，總計視野比人類雙眼僅100度靈活得多。不過，貓僅能聚焦其前30厘米至3米之物件，相對人類而言屬大近視。\n",
      "貓對三原色的辨識力很差，相對人類而言，貓有黃藍色盲且紅綠色辨成灰黃色，與狗相似。關於貓的夜視能力，生物學家發現牛磺酸對貓的視力起了很大作用，貓本身不能合成牛磺酸，必須由外攝取。缺乏牛磺酸，會使視力及夜視能力變差，影響夜間活動。據生物學家稱，貓經常捕鼠，是因老鼠體內含牛磺酸。[52][53]\n",
      "紫外線可以通過貓的晶状体。\n",
      "當四周光線微弱，貓會用感覺毛來改善行動力與感知能力。感覺毛主要分布於鼻子兩側、下巴、雙眼上方、兩頰也有數根。感覺毛可感受非常微弱的空氣波動，視野不清時也能協助辨識阻礙位置。鬍鬚尖端與雙耳連成一線，恰是身體能通過障礙的最小範圍，故貓可在黑夜中快速判斷地形能否通過。\n",
      "貓有第三眼瞼，當貓眼睑張開時，眨眼時第三眼瞼會從旁稍微遮蓋眼睛。若貓生病，或是睡眠，笑著，此眼皮會縮回一部分。若貓長時間嶄露第三眼瞼，表示它的健康有問題。\n",
      "\n",
      "貓爪[编辑]\n",
      "貓的爪子尖銳還能有伸縮作用，能夠向外露張開或是往內縮閉藏起來。貓的趾底有脂肪肉墊，因而行走無聲。而按一下這個肉墊，尖銳的勾爪就會伸出來，養貓的人一般使用這種方法來剪爪。大部分貓都有磨爪的習慣。而貓喜好的磨爪物各不相同。家貓可能會選擇沙發、牆壁甚至人類的衣物等作為自己的磨爪物。\n",
      "\n",
      "感官[编辑]\n",
      "貓的感官適於狩獵。在哺乳類動物中，貓的聽覺、視覺、嗅覺、味覺、觸覺極敏銳。\n",
      "\n",
      "^ 生物學特性和解剖生理特點-醫生在線[永久失效連結]\n",
      "\n",
      "^ 51.0 51.1 51.2 《寵藝透視》. 寵藝透視. 2013-07: 50. \n",
      "\n",
      "^ 貓為什麼要吃老鼠？德國生物學家解開謎團. china.ibtimes.com. [永久失效連結]\n",
      "\n",
      "^ 美國藝術家模擬貓的視覺　記錄貓眼看到的世界景像.   [2014-04-05]. （原始内容存档于2014-04-07）. \n",
      "\n",
      "^ At Home : Care / Health : Understanding Cats.   [2005-08-15]. （原始内容存档于2008-02-01）. \n",
      "\n",
      "^ Strain, G.M., How Well Do Dogs and Other Animals Hear?.   [2007-05-12]. （原始内容存档于2011-08-28）. \n",
      "\n",
      "^ The Nose Knows. About.com.   [2006-11-29]. （原始内容存档于2010-12-06）. \n",
      "\n",
      "^ Li, Xia; Weihua Li, Hong Wang, Jie Cao, Kenji Maehashi, Liquan Huang, Alexander A. Bachmanov, Danielle R. Reed, Véronique Legrand-Defretin, Gary K. Beauchamp, Joseph G. Brand. Pseudogenization of a Sweet-Receptor Gene Accounts for Cats' Indifference toward Sugar. PLOS Genetics (Public Library of Science). 2005-07-25, 1 (1)  [2006-11-08]. doi:10.1371/journal.pgen.0010003. （原始内容存档于2021-03-13）.  引文使用过时参数coauthors (帮助)\n",
      "\n",
      "^ 胡苓芝、李冠群. 三花猫-花色形成的原因(下)（Calico Cat）. 科學Online. 2009-04-27  [2015-02-19]. （原始内容存档于2015-02-19）.\n",
      "\n",
      "聽覺[编辑]\n",
      "貓每隻耳各有32條獨立的肌肉控制耳殼轉動，因此雙耳可單獨朝向不同的音源轉動，使其向獵物移動時仍能對周遭其他音源保持直接接觸。[54]除了蘇格蘭折耳貓這類基因突變的貓以外，貓極少有狗常見的「垂耳」，多數的貓耳向上直立。當貓忿怒或受驚時，耳朵會貼向後方，並發出咆哮與「嘶」聲。\n",
      "貓與人類對低頻聲音靈敏度相若。人類中只有極少數的調音師能聽到20 kHz以上的高頻聲音（8.4度的八度音），貓則可達64kHz（10度的八度音），比人類要高1.6個八度音，甚至比狗要高1個八度；但是貓辨別音差須開最少5度，比起人類辨別音差須開最少0.5度來得粗疏。[51][55]\n",
      "\n",
      "嗅覺[编辑]\n",
      "家貓的嗅覺較人類靈敏14倍[56]。貓的鼻腔內有2億個嗅覺受器，數量甚至超過某些品種的狗（狗嗅覺細胞約1.25億～2.2億）。\n",
      "\n",
      "味覺[编辑]\n",
      "貓早期演化時由於基因突變，失去了甜的味覺，[57]但貓不光能感知酸、苦、鹹味，选择适合自己口味的食物，还能尝出水的味道，这一点是其他动物所不及的。不过总括来说猫的味觉不算完善，相比一般人類平均有9000個味蕾，貓一般平均僅有473個味蕾且不喜好低於室溫之食物。故此，貓辨認食物乃憑嗅覺多於味覺。[51]\n",
      "\n",
      "觸覺[编辑]\n",
      "貓在磨蹭時身上會散發出特別的費洛蒙，當這些獨有的費洛蒙留下時，目的就是在宣誓主權，提醒其它貓這是我的，其實這種行為算是一種標記地盤的象徵，會讓牠們有感到安心及安全感。\u001B[0m\u001B[32;1m\u001B[1;3m猫的特征包括多方面的感官适应性，主要用于狩猎。以下是猫的几个重要特征：\n",
      "\n",
      "1. **视觉**：\n",
      "   - 猫的夜视能力极强，能够在微光下看得很清楚，约为人类的六倍。\n",
      "   - 其眼睛使用了一种蓝绿色的薄膜（Tapetum Lucidum），可以增强在暗处的视力。\n",
      "   - 猫主要能聚焦30厘米至3米的物体，其对颜色的辨认能力较差。\n",
      "\n",
      "2. **听觉**：\n",
      "   - 猫的耳朵能独立旋转，每只耳朵有32条独立肌肉，能很好地捕捉周围声音。\n",
      "   - 它们可以听到高达64kHz的声音，高于人类的听觉范围。\n",
      "\n",
      "3. **嗅觉**：\n",
      "   - 猫的嗅觉比人类灵敏14倍，鼻腔内有2亿个嗅觉受器。\n",
      "   - 猫对气味的敏感程度使它们能选择适合自己的食物。\n",
      "\n",
      "4. **味觉**：\n",
      "   - 猫因基因突变失去了对甜味的感知，但对酸、苦和咸味仍然敏感。\n",
      "   - 猫的味蕾数量较少，通常只有473个。\n",
      "\n",
      "5. **触觉**：\n",
      "   - 猫的身体上有许多感应毛，可以感知微弱的空气波动，帮助它们在视野不清时判断周围环境。\n",
      "   - 触觉毛主要分布在脸部和鼻子两侧。\n",
      "\n",
      "6. **爪子**：\n",
      "   - 猫的爪子尖锐且有伸缩功能，能够在行走时静音。\n",
      "   - 通过按压肉垫，猫的爪子可以伸出，适合爬行和狩猎。\n",
      "\n",
      "猫的这些特征使它们成为高效的猎手和适应各种环境的动物。\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n",
      "{'input': '猫的特征', 'output': '猫的特征包括多方面的感官适应性，主要用于狩猎。以下是猫的几个重要特征：\\n\\n1. **视觉**：\\n   - 猫的夜视能力极强，能够在微光下看得很清楚，约为人类的六倍。\\n   - 其眼睛使用了一种蓝绿色的薄膜（Tapetum Lucidum），可以增强在暗处的视力。\\n   - 猫主要能聚焦30厘米至3米的物体，其对颜色的辨认能力较差。\\n\\n2. **听觉**：\\n   - 猫的耳朵能独立旋转，每只耳朵有32条独立肌肉，能很好地捕捉周围声音。\\n   - 它们可以听到高达64kHz的声音，高于人类的听觉范围。\\n\\n3. **嗅觉**：\\n   - 猫的嗅觉比人类灵敏14倍，鼻腔内有2亿个嗅觉受器。\\n   - 猫对气味的敏感程度使它们能选择适合自己的食物。\\n\\n4. **味觉**：\\n   - 猫因基因突变失去了对甜味的感知，但对酸、苦和咸味仍然敏感。\\n   - 猫的味蕾数量较少，通常只有473个。\\n\\n5. **触觉**：\\n   - 猫的身体上有许多感应毛，可以感知微弱的空气波动，帮助它们在视野不清时判断周围环境。\\n   - 触觉毛主要分布在脸部和鼻子两侧。\\n\\n6. **爪子**：\\n   - 猫的爪子尖锐且有伸缩功能，能够在行走时静音。\\n   - 通过按压肉垫，猫的爪子可以伸出，适合爬行和狩猎。\\n\\n猫的这些特征使它们成为高效的猎手和适应各种环境的动物。'}\n"
     ]
    }
   ],
   "execution_count": 18
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-01T12:29:42.245792Z",
     "start_time": "2025-10-01T12:29:21.079297Z"
    }
   },
   "cell_type": "code",
   "source": "print(agent_executor.invoke({\"input\": \"今天上海天气怎么样\"}))",
   "id": "e54cfb3496d22fd3",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new AgentExecutor chain...\u001B[0m\n",
      "\u001B[32;1m\u001B[1;3m\n",
      "Invoking: `tavily_search_results_json` with `{'query': '今天上海天气'}`\n",
      "\n",
      "\n",
      "\u001B[0m\u001B[36;1m\u001B[1;3m[{'title': '中国气象局-天气预报-城市预报- 上海', 'url': 'https://weather.cma.cn/web/weather/58367.html', 'content': '|  |  |  |  |  |  |  |  |  |\\n ---  ---  ---  --- \\n| 时间 | 11:00 | 14:00 | 17:00 | 20:00 | 23:00 | 02:00 | 05:00 | 08:00 |\\n| 天气 |\\n| 气温 | 34℃ | 34.3℃ | 32℃ | 28.6℃ | 28.1℃ | 27.3℃ | 26.7℃ | 28.6℃ |\\n| 降水 | 2.3mm | 2.3mm | 2.3mm | 2.3mm | 无降水 | 无降水 | 无降水 | 无降水 |\\n| 风速 | 3.3m/s | 3.3m/s | 3m/s | 2.8m/s | 3.2m/s | 3.1m/s | 3m/s | 3.3m/s |\\n| 风向 | 西南风 | 西南风 | 东南风 | 东北风 | 东南风 | 东南风 | 东南风 | 西南风 |\\n| 气压 | 1017.1hPa | 1014.6hPa | 1014.3hPa | 1015.6hPa | 1015hPa | 1014.3hPa | 1013.7hPa | 1014.6hPa | [...] |  |  |  |  |  |  |  |  |  |\\n ---  ---  ---  --- \\n| 时间 | 08:00 | 11:00 | 14:00 | 17:00 | 20:00 | 23:00 | 02:00 | 05:00 |\\n| 天气 |\\n| 气温 | 29.1℃ | 29.9℃ | 29.5℃ | 26℃ | 24.9℃ | 23.8℃ | 23.8℃ | 23.9℃ |\\n| 降水 | 0.9mm | 1.5mm | 5.4mm | 1.6mm | 1.6mm | 0.1mm | 无降水 | 无降水 |\\n| 风速 | 3.3m/s | 3.3m/s | 3.3m/s | 2.9m/s | 2.7m/s | 3.3m/s | 3.1m/s | 3.1m/s |\\n| 风向 | 西北风 | 西北风 | 西北风 | 东北风 | 东南风 | 西北风 | 西北风 | 西北风 |\\n| 气压 | 1013.2hPa | 1012.7hPa | 1012hPa | 1012.3hPa | 1013.3hPa | 1013.3hPa | 1012.7hPa | 1012.2hPa | [...] |  |  |  |  |  |  |  |  |  |\\n ---  ---  ---  --- \\n| 时间 | 08:00 | 11:00 | 14:00 | 17:00 | 20:00 | 23:00 | 02:00 | 05:00 |\\n| 天气 |\\n| 气温 | 27.2℃ | 27℃ | 27.9℃ | 26.9℃ | 24.5℃ | 23.6℃ | 23.6℃ | 23.6℃ |\\n| 降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 | 无降水 |\\n| 风速 | 3.3m/s | 3.1m/s | 3.3m/s | 2.9m/s | 2.7m/s | 3.1m/s | 2.9m/s | 3.1m/s |\\n| 风向 | 东北风 | 东北风 | 东北风 | 东北风 | 东南风 | 东南风 | 东南风 | 东南风 |\\n| 气压 | 1014hPa | 1014hPa | 1012.5hPa | 1012.8hPa | 1014hPa | 1013.1hPa | 1012.3hPa | 1012.2hPa |', 'score': 0.8091708}]\u001B[0m\u001B[32;1m\u001B[1;3m今天上海的天气预报如下：\n",
      "\n",
      "- **天气状况**：多云\n",
      "- **气温**：预期将在34℃至28.1℃之间变化\n",
      "- **降水量**：预计有小雨，降水量在2.3mm左右\n",
      "- **风速**：风速达到3.3m/s，主要来自西南风和东南风\n",
      "\n",
      "详细的天气信息可以访问[中国气象局](https://weather.cma.cn/web/weather/58367.html)。\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n",
      "{'input': '今天上海天气怎么样', 'output': '今天上海的天气预报如下：\\n\\n- **天气状况**：多云\\n- **气温**：预期将在34℃至28.1℃之间变化\\n- **降水量**：预计有小雨，降水量在2.3mm左右\\n- **风速**：风速达到3.3m/s，主要来自西南风和东南风\\n\\n详细的天气信息可以访问[中国气象局](https://weather.cma.cn/web/weather/58367.html)。'}\n"
     ]
    }
   ],
   "execution_count": 19
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 7 添加记忆",
   "id": "dd4d9123496bfc58"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-01T12:37:50.133559Z",
     "start_time": "2025-10-01T12:37:44.164972Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from  langchain_core.chat_history import BaseChatMessageHistory\n",
    "from langchain_community.chat_message_histories import ChatMessageHistory\n",
    "from langchain_core.runnables.history import RunnableWithMessageHistory\n",
    "store = {}\n",
    "\n",
    "# 调取指定session_id对应的memory\n",
    "def get_session_history(session_id:str) -> BaseChatMessageHistory:\n",
    "    if session_id not in store:\n",
    "        store[session_id] = ChatMessageHistory()\n",
    "\n",
    "    return store[session_id]\n",
    "agent_with_chat_history = RunnableWithMessageHistory(\n",
    "    runnable= agent_executor,\n",
    "    get_session_history = get_session_history,\n",
    "    input_messages_key=\"input\",\n",
    "    history_messages_key=\"chat_history\"\n",
    ")\n",
    "\n",
    "response = agent_with_chat_history.invoke(\n",
    "    {\"input\":\"Hi，我的名字是Cyber\"},\n",
    "    config = {\"configurable\": {\"session_id\": \"123\"}},\n",
    ")\n",
    "\n",
    "print(response)"
   ],
   "id": "bc8b454672feee50",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new AgentExecutor chain...\u001B[0m\n",
      "\u001B[32;1m\u001B[1;3m你好，Cyber！有什么我可以帮助你的吗？\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n",
      "{'input': 'Hi，我的名字是Cyber', 'chat_history': [], 'output': '你好，Cyber！有什么我可以帮助你的吗？'}\n"
     ]
    }
   ],
   "execution_count": 22
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-01T12:38:22.597218Z",
     "start_time": "2025-10-01T12:38:16.580666Z"
    }
   },
   "cell_type": "code",
   "source": [
    "response = agent_with_chat_history.invoke(\n",
    "    {\"input\": \"我叫什么名字?\"},\n",
    "    config={\"configurable\": {\"session_id\": \"123\"}},\n",
    ")\n",
    "\n",
    "print(response)"
   ],
   "id": "a9a95697ff7c820e",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new AgentExecutor chain...\u001B[0m\n",
      "\u001B[32;1m\u001B[1;3m你的名字是Cyber！有什么特别的事情想分享吗？\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n",
      "{'input': '我叫什么名字?', 'chat_history': [HumanMessage(content='Hi，我的名字是Cyber', additional_kwargs={}, response_metadata={}), AIMessage(content='你好，Cyber！有什么我可以帮助你的吗？', additional_kwargs={}, response_metadata={})], 'output': '你的名字是Cyber！有什么特别的事情想分享吗？'}\n"
     ]
    }
   ],
   "execution_count": 23
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-10-01T12:38:46.434367Z",
     "start_time": "2025-10-01T12:38:40.383409Z"
    }
   },
   "cell_type": "code",
   "source": [
    "response = agent_with_chat_history.invoke(\n",
    "    {\"input\": \"我叫什么名字?\"},\n",
    "    config={\"configurable\": {\"session_id\": \"4566\"}},\n",
    ")\n",
    "print(response)"
   ],
   "id": "4dc859057156c166",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001B[1m> Entering new AgentExecutor chain...\u001B[0m\n",
      "\u001B[32;1m\u001B[1;3m抱歉，我无法得知您的姓名。如果您愿意，可以告诉我您的名字。\u001B[0m\n",
      "\n",
      "\u001B[1m> Finished chain.\u001B[0m\n",
      "{'input': '我叫什么名字?', 'chat_history': [], 'output': '抱歉，我无法得知您的姓名。如果您愿意，可以告诉我您的名字。'}\n"
     ]
    }
   ],
   "execution_count": 24
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
